package com.fish.admin.module.system.service.impl;

import com.fish.admin.module.system.domain.bo.SysMenuBO;
import com.fish.admin.module.system.domain.entity.SysAuthority;
import com.fish.admin.module.system.domain.entity.SysMenu;
import com.fish.admin.module.system.enums.AuthorityTypeEnum;
import com.fish.admin.module.system.enums.SubjectTypeEnum;
import com.fish.admin.module.system.manager.SysAuthorityManager;
import com.fish.admin.module.system.manager.SysMenuManager;
import com.fish.admin.module.system.manager.SysRoleManager;
import com.fish.admin.module.system.service.SysAuthorityService;
import com.fish.admin.module.system.validator.SystemValidator;
import com.fish.admin.util.ConvertUtils;
import com.fish.common.core.base.AuthorizationInfo;
import com.fish.common.core.base.LoginAppUser;
import com.fish.common.core.base.Role;
import com.fish.common.core.constant.GlobConstants;
import com.fish.common.core.context.UserContextManager;
import com.fish.common.support.util.BeanHelpers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class SysAuthorityServiceImpl implements SysAuthorityService {

    private final SysMenuManager sysMenuManager;
    private final SysAuthorityManager sysAuthorityManager;

    private final SysRoleManager sysRoleManager;

    @Override
    public AuthorizationInfo authorization() {
       LoginAppUser loginAppUser = UserContextManager.getRequiredContext();
       AuthorizationInfo authorization = new AuthorizationInfo();
       authorization.setUserId(loginAppUser.getUserId());
       Role role = loginAppUser.getRole();
       //基于RABC模型，没有角色就没有菜单和按钮权限
        if (Objects.isNull(role)) {
            return authorization;
        }
        List<SysMenu> sysMenuList = sysMenuManager.listByRoleId(role.getId());
        List<SysMenuBO> menus = sysMenuList.stream().map(e -> {
            SysMenuBO m = new SysMenuBO();
            BeanHelpers.copyProperties(e, m);
            m.setAuthorityType(AuthorityTypeEnum.MENU.getValue());
            return m;
        }).collect(Collectors.toList());
        List<SysMenuBO> parents = menus.stream()
                .filter(m -> Objects.equals(GlobConstants.ROOT, m.getParentId()))
                .sorted(Comparator.comparing(SysMenuBO::getSort))
                .collect(Collectors.toList());
        parents.forEach(a ->
            ConvertUtils.setChild(a, menus)
        );
        authorization.setMenus(ConvertUtils.router(parents));
        return authorization;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void grant(Long id, SubjectTypeEnum subjectType, List<Long> menuIds, AuthorityTypeEnum authorityType) {
        SystemValidator.validateRole(id);
        sysAuthorityManager.delete(id,subjectType,authorityType);
        sysAuthorityManager.batchSave(id,subjectType,authorityType,menuIds);

    }

    @Override
    public List<Long> authorize(Long roleId, SubjectTypeEnum subjectType) {
        List<SysAuthority> authorityList = sysAuthorityManager.list(roleId,
                subjectType, AuthorityTypeEnum.MENU);
        return authorityList.stream().map(a -> a.getAuthorityId())
                .collect(Collectors.toList());
    }
}
